#!/usr/bin/python
# -*- coding: UTF-8 -*-
"""
Python 3.x
Flask 2.1.3
Flask-Limiter 2.6.3

Official Manual Address : https://flask-limiter.readthedocs.io/en/stable/index.html

"""
from flask import Flask, current_app
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
from flask_login import current_user

app = Flask(__name__)

# Initialize the limiter object
limiter = Limiter(
    app,
    key_func=get_remote_address,
    default_limits=["200 per day", "50 per hour"],  # 默认速率限制：每天200次访问，每小时50次访问
    storage_uri="memory://",  # 缓存地址
)


@app.route("/slow")
@limiter.limit("1 per day")  # 速率限制：每天1次访问
def slow():
    """
    覆盖默认速率
    :return:
    """
    return ":("


@app.route("/medium")
@limiter.limit("1/second", override_defaults=False)  # 速率限制：在默认速率限制的基础上，添加每秒1次访问
def medium():
    """
    不覆盖默认速率
    :return:
    """
    return ":|"


@app.route("/fast")
def fast():
    """
    默认速率
    :return:
    """
    return ":)"


@app.route("/ping")
@limiter.exempt  # 不受默认速率限制
def ping():
    """
    不受默认速率限制
    :return:
    """
    return "PONG"


@app.route("/single_decorator")
@limiter.limit("100/day;10/hour;1/minute")
def single_decorator():
    """
    单装饰器
    :return:
    """
    return "SINGLE DECORATOR"


@app.route("/multiple_decorators")
@limiter.limit("100/day")
@limiter.limit("10/hour")
@limiter.limit("1/minute")
def multiple_decorators():
    """
    多个装饰器
    :return:
    """
    return "MULTIPLE DECORATORS"


def rate_limit_from_config():
    """
    从配置文件获取配置
    :return:
    """
    return current_app.config.get("CUSTOM_LIMIT", "10/s")


@app.route("/dynamically_limit")
@limiter.limit(rate_limit_from_config())
def dynamically_limit():
    """
    动态获取配置
    :return:
    """
    return "DYNAMICALLY LIMIT"


@app.route("/expensive")
@limiter.limit("100/day", exempt_when=lambda: current_user.is_admin)
def expensive_route():
    """
    指定特定条件，不受速率限制
    :return:
    """
    return "Exemption conditions"


# 公共速率限制
request_limit = limiter.shared_limit("10/hour", scope="request_limit")


@app.route("/r1_shared_request")
@request_limit
def request_r1_limit():
    """
    公共速率限制Route1
    :return:
    """
    return "REQUEST R1 LIMIT"


@app.route("/r2_shared_request")
@request_limit
def request_r2_limit():
    """
    公共速率限制Route2
    :return:
    """
    return "REQUEST R2 LIMIT"


@app.route("/custom_error_msg")
@limiter.limit("10/s", error_message="...")
def custom_error_msg():
    """
    自定义错误消息
    :return:
    """
    return "CUSTOM ERROR MSG"


def error_handler():
    """
    从配置文件中获取错误消息
    :return:
    """
    return current_app.config.get("CUSTOM_ERROR_MSG", "...")


@app.route("/custom_error_msg_from_config")
@limiter.limit("10/s", error_message=error_handler())
def custom_error_msg_from_config():
    """
    自定义错误消息（配置文件）
    :return:
    """
    return "CUSTOM ERROR MSG FROM CONFIG"


if __name__ == '__main__':
    app.run()
